package com.sprite.framework.bone;

import com.sprite.framework.bone.config.JdbcConfig;
import com.sprite.framework.entity.*;
import com.sprite.framework.entity.bridge.JdbcTemplateBridge;
import com.sprite.framework.entity.mapper.DefaultStatementDelegator;
import com.sprite.framework.entity.mapper.StatementDelegator;
import org.apache.commons.dbcp2.BasicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.ResourceLoader;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.util.PathMatcher;

import javax.sql.DataSource;
import java.util.List;

/**
 * @author Jack
 * @since 2.0.1
 */
@Configuration
public class SpriteBoneConfiguration {

    @Autowired(required = false)
    private EntityInterceptor entityInterceptor;

    @Autowired
    private EntityScriptExecutor entityScriptExecutor;

    @Autowired(required = false)
    private List<IdGenerator> generatorList;

    @Bean
    public Delegator delegator(){
        GenericDelegator delegator = new GenericDelegator();
        delegator.setEntityInterceptor(entityInterceptor);
        delegator.addGenerator(generatorList);
        delegator.setScriptExecutor(entityScriptExecutor);
        return delegator;
    }

    @Bean
    public SpringContextUtil springContextUtil(){
        return new SpringContextUtil();
    }

    @Bean
    public EntityScriptExecutor scriptExecutor(DataSource dataSource){
        JdbcTemplateBridge jdbcTemplateBridge = new JdbcTemplateBridge();

        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);
        jdbcTemplateBridge.setJdbcTemplate(jdbcTemplate);

        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        jdbcTemplateBridge.setPlatformTransactionManager(dataSourceTransactionManager);

        return jdbcTemplateBridge;
    }

    @Bean
    public StatementDelegator statementDelegator(){
        return new DefaultStatementDelegator();
    }

    @Bean
    public JdbcConfig jdbcConfig(){
        return new JdbcConfig();
    }

    @Bean
    public DataSource dataSource(JdbcConfig jdbcConfig){
        BasicDataSource basicDataSource = new BasicDataSource();
        basicDataSource.setDriverClassName(jdbcConfig.getJdbcDriverClass());
        basicDataSource.setUrl(jdbcConfig.getJdbcUrl());
        basicDataSource.setUsername(jdbcConfig.getUsername());
        basicDataSource.setPassword(jdbcConfig.getPassword());
        basicDataSource.setInitialSize(jdbcConfig.getInitialSize());
        basicDataSource.setMaxTotal(jdbcConfig.getMaxTotal());
        basicDataSource.setMaxIdle(jdbcConfig.getMaxIdle());
        basicDataSource.setMinIdle(jdbcConfig.getMinIdle());
        basicDataSource.setMaxWaitMillis(jdbcConfig.getMaxWaitMillis());
        basicDataSource.setTestOnBorrow(jdbcConfig.isTestOnReturn());
        basicDataSource.setTestOnCreate(jdbcConfig.isTestOnReturn());
        basicDataSource.setTestOnReturn(jdbcConfig.isTestOnReturn());
        basicDataSource.setTestWhileIdle(jdbcConfig.isTestWhileIdle());
        basicDataSource.setTimeBetweenEvictionRunsMillis(jdbcConfig.getTimeBetweenEvictionRunsMillis());
        basicDataSource.setMinEvictableIdleTimeMillis(jdbcConfig.getMinEvictableIdleTimeMillis());
        basicDataSource.setRemoveAbandonedTimeout(jdbcConfig.getRemoveAbandonedTimeout());
        basicDataSource.setLogAbandoned(jdbcConfig.isLogAbandoned());

        return basicDataSource;
    }

    @Bean
    public PropertyPlaceholderConfigurer propertyPlaceholderConfigurer(ApplicationContext applicationContext) throws Exception{
        PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer();
        propertyPlaceholderConfigurer.setLocations(applicationContext.getResources(System.getProperty("sprite.properties")));
        return propertyPlaceholderConfigurer;
    }
}
